
import { _decorator, Component, Node, Vec3, v3, Material, v4, MeshRenderer } from 'cc';
import Action3dManager, { ActionMngType } from '../../Script/Common/Action3dManager';
import yyComponent from '../../Script/Common/yyComponent';
import MapData from '../../Script/GameSpecial/MapData';
import { ShopDataCfg } from '../../Script/GameSpecial/shopDataCfg';

const car1_0 = { type: 1, id: 0, getType: 0, price: 200, width: 0.45, height: 1.3, len: 0.504, minSpeed: 10, maxSpeed: 15, totalPartCount: 12, rolePos: { x: 0, y: 0.2, z: 0 }, streakPos: [], streakWidth: 0.063, huoYanPos: [], };

const { ccclass, property } = _decorator;
/**车辆 */
@ccclass('Car')
export class Car extends yyComponent {

    onLoad() {
        let mesh = this.node.getComponent(MeshRenderer);
        if (!!mesh) {
            mesh.mesh.struct.minPosition = null;
            mesh.mesh.struct.maxPosition = null;
        }
        let meshs = this.node.getComponentsInChildren(MeshRenderer);
        for (let i = meshs.length - 1; i >= 0; --i) {
            meshs[i].mesh.struct.minPosition = null;
            meshs[i].mesh.struct.maxPosition = null;
        }
    }

    @property(Material)
    protected mat: Material = null;
    @property(Material)
    protected matBanZi: Material = null;

    //当前材质球设置的参数对应的关卡编号
    protected static matDataLevel: number = null;
    protected initMat() {
        if (!this.mat) {
            return;
        }
        let lv = MapData.getCurDataLevel();
        if (null === lv) {
            this.setMatDefaultData();
        } else if (lv != Car.matDataLevel) {
            this.setMatMapData();
        }
    }
    protected setMatDefaultData() {
        if (Car.matDataLevel === 0) {
            return;
        }
        Car.matDataLevel = 0;
        //设置参数
        let pathLen = v4(1000, 0, 0, 0);
        let mat = this.mat;
        let data = [v4(0, 0, 0, 1000), v4(0, 0, 0, 1)];
        this.setMatData(mat, "pathLen", pathLen);
        this.setMatData(mat, "pEnd1", data[0]);
        this.setMatData(mat, "pEnd2", data[1]);
        this.setMatData(mat, "pathState", v4(1, 0, 0, 0));

        mat = this.matBanZi;
        this.setMatData(mat, "pathLen", pathLen);
        this.setMatData(mat, "pEnd1", data[0]);
        this.setMatData(mat, "pEnd2", data[1]);
        this.setMatData(mat, "pathState", v4(1, 0, 0, 0));
    }

    protected setMatMapData() {
        let lv = MapData.getCurDataLevel();
        if (Car.matDataLevel === lv) {
            return;
        }
        Car.matDataLevel = lv;
        let data = MapData.getMatData();
        let len = MapData.getTotalLen();
        let pathLen = v4(len, 0, 0, 0);
        let mat = this.mat;
        this.setMatData(mat, "pathLen", pathLen);
        let j = 0;
        this.setMatData(mat, "p11", data[j++]);
        this.setMatData(mat, "p12", data[j++]);
        this.setMatData(mat, "p21", data[j++]);
        this.setMatData(mat, "p22", data[j++]);
        this.setMatData(mat, "p31", data[j++]);
        this.setMatData(mat, "p32", data[j++]);
        this.setMatData(mat, "p41", data[j++]);
        this.setMatData(mat, "p42", data[j++]);
        this.setMatData(mat, "p51", data[j++]);
        this.setMatData(mat, "p52", data[j++]);
        this.setMatData(mat, "p61", data[j++]);
        this.setMatData(mat, "p62", data[j++]);
        this.setMatData(mat, "p71", data[j++]);
        this.setMatData(mat, "p72", data[j++]);
        this.setMatData(mat, "p81", data[j++]);
        this.setMatData(mat, "p82", data[j++]);
        this.setMatData(mat, "p91", data[j++]);
        this.setMatData(mat, "p92", data[j++]);
        this.setMatData(mat, "pa1", data[j++]);
        this.setMatData(mat, "pa2", data[j++]);
        this.setMatData(mat, "pEnd1", data[j++]);
        this.setMatData(mat, "pEnd2", data[j++]);
        this.setMatData(mat, "pathState", v4(1, 0, 0, 0));

        mat = this.matBanZi;
        this.setMatData(mat, "pathLen", pathLen);
        j = 0;
        this.setMatData(mat, "p11", data[j++]);
        this.setMatData(mat, "p12", data[j++]);
        this.setMatData(mat, "p21", data[j++]);
        this.setMatData(mat, "p22", data[j++]);
        this.setMatData(mat, "p31", data[j++]);
        this.setMatData(mat, "p32", data[j++]);
        this.setMatData(mat, "p41", data[j++]);
        this.setMatData(mat, "p42", data[j++]);
        this.setMatData(mat, "p51", data[j++]);
        this.setMatData(mat, "p52", data[j++]);
        this.setMatData(mat, "p61", data[j++]);
        this.setMatData(mat, "p62", data[j++]);
        this.setMatData(mat, "p71", data[j++]);
        this.setMatData(mat, "p72", data[j++]);
        this.setMatData(mat, "p81", data[j++]);
        this.setMatData(mat, "p82", data[j++]);
        this.setMatData(mat, "p91", data[j++]);
        this.setMatData(mat, "p92", data[j++]);
        this.setMatData(mat, "pa1", data[j++]);
        this.setMatData(mat, "pa2", data[j++]);
        this.setMatData(mat, "pEnd1", data[j++]);
        this.setMatData(mat, "pEnd2", data[j++]);
        this.setMatData(mat, "pathState", v4(1, 0, 0, 0));
    }
    protected setMatData(mat: Material, str: string, data) {
        let pass = mat.passes[0];
        let handle = pass.getHandle(str);
        pass.setUniform(handle, data);
    }

    protected initSub() {
        this.initMat();
        this.initParts();
        this.initSpeed();
    }
    protected resetSub() {
        // this.initMat();
        this.resetParts();
        this.resetSpeed();
    }

    public reuse() {
        this.reset();
        this.initMat();
    }

    /*****************************************对外接口*****************************************/
    /**车辆当前速度 */
    public getSpeed() {
        return this.curSpeed;
    }
    /**当前有效零件数量 */
    public getPartCount() {
        return this.curPartCount;
    }
    /**总的零件数量 */
    public getTotalPartCount() {
        return this.totalPartCount;
    }
    /**零件分组数量 */
    public getPartGroupCount() {
        return this.partGroupCount;
    }
    public getCurPartPtr() {
        return this.curEnabledPartPtr;
    }
    public isPartFull() {
        return this.curPartCount >= this.totalPartCount;
    }
    public setPartCount(count: number) {
        if (count > this.totalPartCount) {
            count = this.totalPartCount;
        }
        this.curPartCount = count;
        if (this.carId == 0) {
            return;
        }
        let r = this.curPartCount / this.totalPartCount;
        let ptr = Math.ceil(this.partGroupCount * r) - 1;
        for (let i = 0; i <= ptr; ++i) {
            this.showPart(i);
        }
        this.curEnabledPartPtr = ptr;
        this.updateSpeed();
    }
    /**
     * 收集零件
     * @param count 零件数量
     */
    public addPartCount(count: number) {
        if (count > this.totalPartCount - this.curPartCount) {
            this.curPartCount = this.totalPartCount;
        } else {
            this.curPartCount += count;
        }
        this.updateSpeed();
        let r = this.curPartCount / this.totalPartCount;
        let ptr = Math.ceil(this.partGroupCount * r) - 1;
        if (this.carId == 0) {
            this.curEnabledPartPtr = ptr;
            this.playFalseAddPartAnim(ptr);
            return count;
        }
        if (ptr > this.curEnabledPartPtr) {
            for (let i = this.curEnabledPartPtr + 1; i <= ptr; ++i) {
                this.playAddPartAnim(i);
            }
            this.curEnabledPartPtr = ptr;
        } else if (this.curEnabledPartPtr + 1 < this.partGroupCount) {
            this.playFalseAddPartAnim(this.curEnabledPartPtr + 1);
        }
        return count;
    }

    /**
     * 撞到障碍物，掉落零件
     * @param count 零件数量
     */
    public dropPartCount(count: number) {
        if (count > this.curPartCount) {
            this.curPartCount = 0;
            count = this.curPartCount;
        } else {
            this.curPartCount -= count;
        }
        this.updateSpeed();
        if (this.carId === 0) {
            this.playFalseDropPartAnim(this.curEnabledPartPtr);
            return count;
        }
        let r = this.curPartCount / this.totalPartCount;
        let ptr = Math.ceil(this.partGroupCount * r) - 1;
        if (ptr < this.curEnabledPartPtr) {
            for (let i = this.curEnabledPartPtr; i > ptr; --i) {
                this.playDropPartAnim(i);
            }
            this.curEnabledPartPtr = ptr;
        } else if (this.curEnabledPartPtr + 1 < this.partGroupCount) {
            this.playFalseDropPartAnim(this.curEnabledPartPtr + 1);
        } else {
            this.playFalseDropPartAnim(this.curEnabledPartPtr);
        }
        return count;
    }

    /**获取车辆用于碰撞范围计算的尺寸 */
    public getSize(): { width: number, height: number, len: number } {
        return this.getCarData();
    }
    /**拖尾偏移坐标 */
    public getStreakPos(): { x: number, y: number, z: number }[] {
        return this.getCarData().streakPos;
    }
    /**获取车辆数据，预留接口 */
    public getCarData(): any {
        if (this.type == 1 && this.carId == 0) {
            // return ShopDataCfg[this.type][this.carId];
            return car1_0;
        } else {
            return ShopDataCfg[this.type][this.carId - 1];
        }
    }
    public getHuoYanPos(): { x: number, y: number, z: number }[] {
        return this.getCarData().huoYanPos;
    }

    protected getCarScale() {
        switch (this.type) {
            case 1: {
                return this.carId > 0 ? 2 : 1;
            }
            case 2: return 1.3;
            case 3: {
                return this.carId == 3 ? 1 : 1.4;
            }
        }
        return 1;
    }
    /*****************************************管理对象*****************************************/
    //#region 零件分组
    //可以拆分显示的零件分组
    @property(Node)
    protected part0: Node[] = [];
    @property(Node)
    protected part1: Node[] = [];
    @property(Node)
    protected part2: Node[] = [];
    @property(Node)
    protected part3: Node[] = [];
    @property(Node)
    protected part4: Node[] = [];
    @property(Node)
    protected part5: Node[] = [];
    @property(Node)
    protected part6: Node[] = [];
    @property(Node)
    protected part7: Node[] = [];
    @property(Node)
    protected part8: Node[] = [];
    @property(Node)
    protected part9: Node[] = [];

    protected allParts: Node[][] = [];
    /**零件分组数量 */
    public partGroupCount: number;
    /**当前有效的部件是第几组，-1表示全部可拆分零件都没显示 */
    protected curEnabledPartPtr: number;
    /**每个零件在正常状态下的坐标角度缩放 */
    protected partTransf: { [name: string]: { p: Vec3, e: Vec3, s: Vec3, p2: Vec3 } } = {};

    protected initParts() {
        this.allParts = [];
        if (this.part0.length > 0) {
            this.allParts.push(this.part0);
        }
        if (this.part1.length > 0) {
            this.allParts.push(this.part1);
        }
        if (this.part2.length > 0) {
            this.allParts.push(this.part2);
        }
        if (this.part3.length > 0) {
            this.allParts.push(this.part3);
        }
        if (this.part4.length > 0) {
            this.allParts.push(this.part4);
        }
        if (this.part5.length > 0) {
            this.allParts.push(this.part5);
        }
        if (this.part6.length > 0) {
            this.allParts.push(this.part6);
        }
        if (this.part7.length > 0) {
            this.allParts.push(this.part7);
        }
        if (this.part8.length > 0) {
            this.allParts.push(this.part8);
        }
        if (this.part9.length > 0) {
            this.allParts.push(this.part9);
        }
        this.partGroupCount = this.allParts.length;
        this.curEnabledPartPtr = -1;

        let children = this.node.children;
        let s = 4 / this.getCarScale();
        if (this.carId == 0) {
            s *= 0.8;
        }
        for (let i = 0, c = children.length; i < c; ++i) {
            let node = children[i];
            this.partTransf[node.name] = {
                //原始坐标
                p: v3(node.position),
                e: v3(node.eulerAngles),
                s: v3(node.scale),
                //组装时散开阶段移动到的位置
                p2: v3(node.position).normalize().multiplyScalar(s),
            }
        }

        this.hideAllParts();
    }
    protected resetParts() {
        this.curEnabledPartPtr = -1;
        this.hideAllParts();
        for (let i = this.node.children.length - 1; i >= 0; --i) {
            let node = this.node.children[i];
            let tr = this.partTransf[node.name];
            if (!!tr) {
                node.setPosition(tr.p);
                node.setScale(tr.s);
                node.eulerAngles = tr.e;
            }
        }
    }
    protected hidePart(ptr: number) {
        let actMng = Action3dManager.getMng(ActionMngType.Level);
        let part = this.allParts[ptr];
        for (let i = part.length - 1; i >= 0; --i) {
            actMng.stopAllActions(part[i]);
            part[i].active = false;
        }
    }
    protected showPart(ptr: number) {
        let actMng = Action3dManager.getMng(ActionMngType.Level);
        let part = this.allParts[ptr];
        for (let i = part.length - 1; i >= 0; --i) {
            let node = part[i];
            actMng.stopAllActions(node);
            node.active = true;
            let tr = this.partTransf[node.name];
            node.setPosition(tr.p);
            node.setScale(tr.s);
            node.eulerAngles = tr.e;
        }
    }
    protected hideAllParts() {
        for (let i = 0; i < this.partGroupCount; ++i) {
            this.hidePart(i);
        }
    }
    protected showAllParts() {
        for (let i = 0; i < this.partGroupCount; ++i) {
            this.showPart(i);
        }
    }
    /**
     * 播放零件收集动画
     * @param ptr 第几组零件
     */
    protected playAddPartAnim(ptr: number) {
        let actMng = Action3dManager.getMng(ActionMngType.Level);
        let parts = this.allParts[ptr];
        for (let i = parts.length - 1; i >= 0; --i) {
            let node = parts[i];
            node.active = true;
            node.setScale(0, 0, 0);
            let n = node.name;
            let tr = this.partTransf[n];
            node.setPosition(tr.p);
            node.eulerAngles = tr.e;

            let delay = Action3dManager.delay(i * 0.1);
            //第一阶段：放大
            let d0 = 0.3;
            let scale00 = Action3dManager.scaleTo(0, tr.s);

            let move0 = Action3dManager.moveTo(d0, tr.p2);
            move0.easing(Action3dManager.easeOut(2));
            //第二阶段：归位
            let d1 = 0.15;
            let move1 = Action3dManager.moveTo(d1, tr.p);
            move1.easing(Action3dManager.easeIn(2));

            let seq = Action3dManager.sequence(delay, scale00, move0, move1);
            actMng.runAction(node, seq);
        }
    }
    //假的收集动画：只播放零件收集动画，不实际增加零件
    protected playFalseAddPartAnim(ptr: number) {
        let actMng = Action3dManager.getMng(ActionMngType.Level);
        let parts = this.allParts[ptr];
        for (let i = parts.length - 1; i >= 0; --i) {
            let node = parts[i];
            node.active = true;
            node.setScale(0, 0, 0);
            let n = node.name;
            let tr = this.partTransf[n];
            node.setPosition(tr.p);
            node.eulerAngles = tr.e;

            let delay = Action3dManager.delay(i * 0.1);
            //第一阶段：放大
            let d0 = 0.3;
            let scale00 = Action3dManager.scaleTo(0, tr.s);

            let move0 = Action3dManager.moveTo(d0, tr.p2);
            move0.easing(Action3dManager.easeOut(2));
            //第二阶段：归位
            let d1 = 0.15;
            let move1 = Action3dManager.moveTo(d1, tr.p);
            move1.easing(Action3dManager.easeIn(2));

            //动画结束后隐藏
            let cb = Action3dManager.callFun(() => {
                node.active = false;
            });
            let seq = Action3dManager.sequence(delay, scale00, move0, move1, cb);
            actMng.runAction(node, seq);
        }
    }

    protected playDropPartAnim(ptr: number) {
        let parts = this.allParts[ptr];
        for (let i = parts.length - 1; i >= 0; --i) {
            let node = parts[i];
            this.playDropOnePart(node);
        }
    }
    protected playDropOnePart(node: Node) {
        let n = node.name;
        let tr = this.partTransf[n];
        let d0 = 0.8;
        let rotate0 = Action3dManager.rotateTo(d0, Math.random() * 90, Math.random() * 90, Math.random() * 90);
        let x = Math.random() * 2 + 1;
        if (tr.p.x < 0) {
            x = -x;
        }
        let y = 1 + Math.random() * 1;
        let z = -4 - Math.random() * 6;
        let g = 40 + Math.random() * 20;
        let ss = 1 / this.getCarScale();
        x *= ss;
        y *= ss;
        z *= ss;
        g *= ss;
        let move0 = Action3dManager.jumpTo(d0, x, y, z, g);
        let spawn0 = Action3dManager.spawn(rotate0, move0);
        let cb = Action3dManager.callFun(() => {
            node.active = false;
        });
        let seq = Action3dManager.sequence(spawn0, cb);
        let actMng = Action3dManager.getMng(ActionMngType.Level);
        actMng.runAction(node, seq);
    }
    protected playFalseDropPartAnim(ptr: number) {
        let actMng = Action3dManager.getMng(ActionMngType.Level);
        let parts = this.allParts[ptr];
        for (let i = parts.length - 1; i >= 0; --i) {
            let node = parts[i];
            node.active = true;
            let n = node.name;
            let tr = this.partTransf[n];
            node.setPosition(tr.p);
            node.setScale(tr.s);
            node.eulerAngles = tr.e;
            let d0 = 0.8;
            let rotate0 = Action3dManager.rotateTo(d0, Math.random() * 90, Math.random() * 90, Math.random() * 90);
            let x = Math.random() * 2 + 1;
            if (tr.p.x < 0) {
                x = -x;
            }
            let y = 1 + Math.random() * 1;
            let z = -4 - Math.random() * 6;
            let g = 40 + Math.random() * 20;
            let ss = 1 / this.getCarScale();
            x *= ss;
            y *= ss;
            z *= ss;
            g *= ss;
            let move0 = Action3dManager.jumpTo(d0, x, y, z, g);
            let spawn0 = Action3dManager.spawn(rotate0, move0);
            let cb = Action3dManager.callFun(() => {
                node.active = false;
            });
            let seq = Action3dManager.sequence(spawn0, cb);
            actMng.runAction(node, seq);
        }
    }
    //#endregion

    /*****************************************属性数据*****************************************/


    @property
    protected type: number = 1;
    @property
    protected carId: number = 1;

    //#region 速度属性
    protected minSpeed: number;
    protected maxSpeed: number;
    protected curSpeed: number;
    /**车辆可拆分的总的零件数量 */
    protected totalPartCount: number;
    /**车辆当前已收集的零件数量 */
    protected curPartCount: number;
    protected initSpeed() {
        let data = this.getCarData();
        this.minSpeed = data.minSpeed;
        this.maxSpeed = data.maxSpeed;
        this.totalPartCount = data.totalPartCount;
        this.curPartCount = 0;
        this.curSpeed = this.minSpeed;
    }
    protected resetSpeed() {
        this.curPartCount = 0;
        this.curSpeed = this.minSpeed;
    }
    protected updateSpeed() {
        let r = this.curPartCount / this.totalPartCount;
        this.curSpeed = this.minSpeed + (this.maxSpeed - this.minSpeed) * r;
    }
    //#endregion

}


